package com.shelpe.services.sinbad.controller.sinbad;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Order;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.shelpe.services.sinbad.dto.UserViewDto;
import com.shelpe.services.sinbad.entity.jpa.User;
import com.shelpe.services.sinbad.entity.jpa.UserInfo;
import com.shelpe.services.sinbad.repository.jpa.UserInfoRepository;
import com.shelpe.services.sinbad.repository.jpa.UserRepository;
import com.shelpe.services.sinbad.service.UserSmsService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;
import lombok.Data;

@RestController
@RequestMapping(value = "/sinbadservice/v2")
@Api("v2版用户相关的API")
public class User2Controller {
	public final static Predicate[] TEMPLATE = new Predicate[0];
	public final static int USER_TYPE_PURCHASE = 1;
	public final static int USER_TYPE_PROXY = 2;
	public final static int USER_TYPE_PRIMARY = 3;

	@Autowired
	private EntityManager em;
	@Autowired
	private UserInfoRepository userInfoRepository;
	@Autowired
	private UserRepository userRepository;
	@Autowired
	private UserSmsService userSmsService;

	// @RequestParam(name = "function_status", required = false) @ApiParam(value
	// = "功能使用状态", allowableValues = "all,use,nouse,pause") String
	// functionstatus
	@ApiOperation(value = "根据时间来判断发送给不同用户")
	@RequestMapping(path = "/users/@time_type", method = RequestMethod.GET)
	public UserMobileDto findTimeType(
			@RequestParam(name = "type") @ApiParam(value = "类型", allowableValues = "fourth,fifth,index2serven,index2three,index2one") String type) {
		return this.userSmsService.findBySmsUser(type);
	}

	@Data
	public static class UserMobileDto {
		private List<UserViewDto> all;
		private List<UserViewDto> use;
		private List<UserViewDto> nouse;
		private List<UserViewDto> pause;
	}

	@ApiOperation(value = "获取用户（分页）")
	@RequestMapping(path = "/users/@query", method = RequestMethod.GET)
	@ResponseBody
	public Page<UserViewDto> pageQuery(@RequestParam(name = "page_num", defaultValue = "0") int page,
			@RequestParam(name = "page_size", defaultValue = "15") int size,
			@RequestParam(name = "search_title", required = false) final String searchTitle,
			@RequestParam(name = "user_type", required = false, defaultValue = "order") final String userType) {
		// CriteriaBuilder,用来构建CritiaQuery的构建器对象
		CriteriaBuilder criteriaBuilder = em.getCriteriaBuilder();
		// CriteriaQuery,它包含着查询语句的条件各个部分，比如：select 、from、where、group by、orderby等
		CriteriaQuery<User> criteriaQuery = criteriaBuilder.createQuery(User.class);
		// 查询根，用于获取查询实例的属性，通过CriteriaQuery的from方法获取
		Root<User> rootFrom = criteriaQuery.from(User.class);
		// 查询条件
		List<Predicate> predicates = new ArrayList<Predicate>();
		if ("agency".equals(userType)) {
			predicates.add(criteriaBuilder.equal(rootFrom.get("userType"), USER_TYPE_PROXY));
		} else {
			predicates.add(criteriaBuilder.equal(rootFrom.get("userType"), USER_TYPE_PURCHASE));
		}
		if (StringUtils.isNotBlank(searchTitle)) {
			predicates.add(criteriaBuilder.like(rootFrom.get("nick"), "%" + searchTitle + "%"));
		}
		// 格式化参数
		criteriaQuery.where(criteriaBuilder.and(predicates.toArray(TEMPLATE)));
		// 默认按照id排序（从小到大）
		List<Order> orders = new ArrayList<Order>();
		orders.add(criteriaBuilder.desc(rootFrom.get("createdTime")));
		criteriaQuery.orderBy(orders);
		// SQL查询对象
		TypedQuery<User> createQuery = em.createQuery(criteriaQuery);
		// 分页参数
		Integer pageSize = size;
		Integer pageNo = page;
		// 计数查询结果条数
		TypedQuery<User> createCountQuery = em.createQuery(criteriaQuery);
		// 实际查询返回分页对象
		createQuery.setFirstResult(pageNo);
		createQuery.setMaxResults(pageSize);

		List<UserViewDto> dtos = new ArrayList<UserViewDto>();
		if (createQuery.getResultList() != null && createQuery.getResultList().size() > 0) {
			for (User po : createQuery.getResultList()) {
				UserViewDto dto = new UserViewDto();
				dto.from(po);
				dtos.add(dto);
			}
		}
		return new PageImpl<UserViewDto>(dtos, new PageRequest(page, size), createCountQuery.getResultList().size());
	}

	@ApiOperation(value = "用户数据更新填充")
	@RequestMapping(path = "/users/{user_id}/@info", method = RequestMethod.POST)
	@ResponseBody
	public Response createUserInfo(@PathVariable("user_id") long userID, @RequestBody UserInfoDto dto) {
		User user = this.userRepository.findOne(userID);
		Assert.notNull(user, "该用户不存在");
		UserInfo po = dto.to();
		po.setUserID(userID);
		if(user.getPurchaseFrom() == null){
			SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
			try {
				user.setPurchaseFrom(format.parse("1970-01-01 00:00:00"));
			} catch (ParseException e) {
				e.printStackTrace();
			}
		}
		this.userInfoRepository.save(po);
		/** 更新用户status字段 **/
		user.setStatus(1);// 1为已填写联系方式
		if (user.getCreatedTime() == null) {
			user.setCreatedTime(new Date());
		}
		this.userRepository.save(user);

		Response res = new Response();
		res.setStatus(true);
		return res;
	}

	@Data
	private static class Response {
		private boolean status;
	}

	@Data
	private static class UserInfoDto {
		private long tel;
		private long qq;

		public UserInfo to() {
			UserInfo po = new UserInfo();
			if (this.qq > 0) {
				po.setQq(String.valueOf(this.qq));
			}
			po.setTel(String.valueOf(this.tel));
			return po;
		}
	}
}
